﻿#region License
/* ---------------------------------------------------------------- *
 *
 * This file is part of the Xcoordination Application Space
 * ("XcoAppSpace") http://www.xcoordination.com
 *
 * Copyright (C) 2009 Xcoordination http://www.xcoordination.com
 *
 * XcoAppSpace is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General
 * Public License as published by the Free Software Foundation.
 *
 * XcoAppSpace is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/
 * or write to the Free Software Foundation, Inc., 51 Franklin
 * Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * ---------------------------------------------------------------- */
#endregion

using System;
using System.Text;
using System.IO;
using XcoAppSpaces.Contracts.Transport;
using System.Diagnostics;
using XcoAppSpaces.Contracts.Logging;

namespace XcoAppSpaces.Transport.Jabber
{
    ///<summary>
    /// Helperclass for XcoMessage convert for transfer
    ///</summary>
    public class TransferHelper
    {
        private readonly IXcoLogger _log;
        private static readonly int IntByteLength = BitConverter.GetBytes(1).Length;

        ///<summary>
        /// Helper class for XcoMessages converts
        ///</summary>
        public TransferHelper()
        {
            _log = XcoLoggerFactory.CreateInstance(GetType());
        }

        public byte[] Convert(XcoMessage msg, string localAddress)
        {
        	try
            {
                int addrLen = 0;
                int contentInfoLen = 0;
                int contextLen = msg.CausalityContext != null ? msg.CausalityContext.Length : 0;
                int contentLen = msg.Content != null ? msg.Content.Length : 0;
                byte[] addr = null;
				if (!string.IsNullOrEmpty(localAddress))
                {
					addr = Encoding.UTF8.GetBytes(localAddress);
                    addrLen = addr.Length;
                }
                byte[] contentInfo = null;
                if (!string.IsNullOrEmpty(msg.ContentInfo))
                {
                    contentInfo = Encoding.UTF8.GetBytes(msg.ContentInfo);
                    contentInfoLen = contentInfo.Length;
                }

                var memStream = new MemoryStream();
                byte[] len = BitConverter.GetBytes(addrLen + contentInfoLen + contextLen + contentLen + 4 * IntByteLength);
                memStream.Write(len, 0, len.Length);
                len = BitConverter.GetBytes(addrLen);
                memStream.Write(len, 0, len.Length);
                len = BitConverter.GetBytes(contentInfoLen);
                memStream.Write(len, 0, len.Length);
                len = BitConverter.GetBytes(contextLen);
                memStream.Write(len, 0, len.Length);
                len = BitConverter.GetBytes(contentLen);
                memStream.Write(len, 0, len.Length);
                if (addr != null && addr.Length > 0)
                {
                    memStream.Write(addr, 0, addr.Length);
                }
                if (contentInfo != null && contentInfo.Length > 0)
                {
                    memStream.Write(contentInfo, 0, contentInfo.Length);
                }
                if (msg.CausalityContext != null && msg.CausalityContext.Length > 0)
                {
                    memStream.Write(msg.CausalityContext, 0, msg.CausalityContext.Length);
                }
                if (msg.Content != null && msg.Content.Length > 0)
                {
                    memStream.Write(msg.Content, 0, msg.Content.Length);
                }
                return memStream.ToArray();
            }
            catch (Exception err)
            {
                _log.Error("Error converting XcoMessage to byte[]", err);
                return null;
            }
        }



        public XcoMessage Convert(byte[] data, out string remoteAddress)
        {
        	remoteAddress = null;
            try
            {
                int gesamtLen = BitConverter.ToInt32(data, 0);
                int addrLen = BitConverter.ToInt32(data, IntByteLength);
                int contextInfoLen = BitConverter.ToInt32(data, IntByteLength * 2);
                int contextLen = BitConverter.ToInt32(data, IntByteLength * 3);
                int contentLen = BitConverter.ToInt32(data, IntByteLength * 4);
                int index = IntByteLength * 5;
                //Debug.Assert(gesamtLen == addrLen + contextInfoLen + contextLen + contentLen + 4 * IntByteLength, "Length error");


                string addrStr = null;
                string contentInfoStr = null;
                byte[] context = null;
                byte[] content = null;
                if (addrLen > 0)
                {
                    addrStr = Encoding.UTF8.GetString(data, index, addrLen);
                    index += addrLen;
                }
                if (contextInfoLen > 0)
                {
                    contentInfoStr = Encoding.UTF8.GetString(data, index, contextInfoLen);
                    index += contextInfoLen;
                }
                if (contextLen > 0)
                {
                    context = new byte[contextLen];
                    Array.Copy(data, index, context, 0, context.Length);
                    index += context.Length;
                }
                if (contentLen > 0)
                {
                    content = new byte[contentLen];
                    Array.Copy(data, index, content, 0, content.Length);
                }

            	remoteAddress = addrStr;
                return new XcoMessage
                           {
                               ContentInfo = contentInfoStr,
                               CausalityContext = context,
                               Content = content
                           };

            }
            catch (Exception err)
            {
                _log.Error("Error converting stream to XcoMessage. Error:", err);

            }
            return null;
        }
    }
}
